# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function
from flask import current_app
from config import BaseConfig
from backend import LOG
from backend.service_manager.model import *
from backend.exceptions import ModelException, BusinessServiceException
from ..ai_service import fc_map


default_ai_service_template_map = BaseConfig.DEFAULT_AI_SERVICE_TEMPLATE_MAP


class BusinessRequest(object):
    def __init__(self, user_id, business_service_id, **kwargs):
        try:
            self.business_service_id = business_service_id
            self.business_service = business_service_manager.select_first(
                id=self.business_service_id
            )
            self.user_id = user_id
            self.ai_service_chain = self.business_service.ai_pipeline
            self.status = BusinessRequestStatus.in_progress.name
            self.business_request = business_request_manager.create(
                user_id=self.user_id,
                business_service_id=self.business_service_id,
                ai_service_chain=self.ai_service_chain,
                status=self.status,
            )
            self.business_request_log = business_request_log_manager.create(
                user_id=self.user_id,
                business_service_id=self.business_service_id,
                business_request_id=self.business_request.id,
                status=self.status,
            )
        except (ModelException, BusinessServiceException) as e:
            LOG.error("初始化Business Request异常：%s" % e.message)
            raise e
        if kwargs:
            self.ext = kwargs
        else:
            self.ext = dict()
        self.ai_service_objs = list()
        self.current_ai_service_obj = None
        self.completion_count = 0
        self.completion_ratio = 0.0
        self.result = dict()

    # 业务服务请求超时的客户端处理
    def handle_timeout(self):
        pass

    TIMEOUT = BaseConfig.BUSINESS_SERVICE_REQUEST_TIMEOUT
    TIMEOUT_HANDLER = handle_timeout

    def set_ai_service_objs(self):
        for order, item in enumerate(self.ai_service_chain):
            ai_template_id = self.choose_ai_template(item["type"])
            # 依据ai服务类型，实例化ai_service子类的对象
            ai_req_obj = fc_map[item["type"]](item["ai_service_id"], ai_template_id)
            self.ai_service_objs.append(ai_req_obj)
        business_request_manager.update(
            self.business_request,
            ai_request_chain=[i.ai_request.id for i in self.ai_service_objs],
        )

    def choose_ai_template(self, ai_service_type):
        if self.ext and ai_service_type in self.ext:
            return self.ext[ai_service_type]
        if ai_service_type not in default_ai_service_template_map:
            raise BusinessServiceException(
                message=u"业务服务:%d AI服务类型: %s 缺少相应AI模版配置"
                % (self.business_service_id, ai_service_type)
            )
        return default_ai_service_template_map[ai_service_type]

    def update_current_ai_service(self):  # 调用ai服务之前调用
        if self.current_ai_service_obj:
            ai_type = self.current_ai_service_obj.ai_service.type
            business_request_manager.update(
                self.business_request, current_ai_service=ai_type
            )

    def update_completion_ratio(self):  # 调用ai服务员完毕调用
        if self.current_ai_service_obj:
            self.completion_count += 1
            self.completion_ratio = self.completion_count / len(self.ai_service_chain)
            business_request_manager.update(
                self.business_request, completion_ratio=self.completion_ratio
            )

    def save_result(self):
        if self.current_ai_service_obj:
            ai_req_id = self.current_ai_service_obj.ai_request.id
            ai_req_result = self.current_ai_service_obj.wfw_response
            # TODO：全量的业务服务返回值信息最好记录在Nosql
            self.result.update({ai_req_id: ai_req_result})

    def save_request(self):
        kwargs = dict(result=self.result, status=self.status, end_time=datetime.now(),)
        business_request_manager.update(self.business_request, **kwargs)

    def save_log(self):
        kwargs = dict(status=self.status, end_time=datetime.now())
        business_request_log_manager.update(self.business_request_log, **kwargs)

    def save_request_done(self):
        self.status = BusinessRequestStatus.done.name
        self.save_request()
        self.save_log()

    def save_request_failed(self):
        self.status = BusinessRequestStatus.failed.name
        self.save_request()
        self.save_log()

    def save_img_url(self, img_url):
        business_request_log_manager.update(self.business_request_log, media_url=img_url)

    def save_source_type(self, source_type):
        business_request_log_manager.update(self.business_request_log, source_type=SourceType[source_type].name)

    def set_task_id(self):
        if self.ext and "task_id" in self.ext:
            business_request_manager.update(self.business_request, task_id=self.ext["task_id"])
            business_request_log_manager.update(self.business_request_log, task_id=self.ext["task_id"])
